home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / mail / mh / vmail / vmail.3of3 < prev    next >
Encoding:
Text File  |  1991-04-05  |  14.3 KB  |  578 lines

  1. (Message mh:8)
  2. Resent: Mon, 25 Mar 91 10:19:23 PST
  3. Resent: qq11@uxb.liv.ac.uk (Alan Thew)
  4. Resent: Mon, 18 Mar 91 12:22:39 PST
  5. Resent: jcohn@nsf.gov (Johnathan Charles Cohn)
  6. Resent: rjg@sq.com (Bob Gibson)
  7. Resent: dak@sq.com (David Keldson)
  8. Resent: sow@cad.luth.se (Sven-Ove Westberg)
  9. Resent: cenkl@linus.mitre.org (Mike Cenkl)
  10. Resent: david@scocan.sco.com (David J Fiander)
  11. Return-Path: jamesp@metolius.WR
  12. To: luj@ecn.purdue.edu (Jun Lu), jkm@ctt.bellcore.COM (James Mcglashan),
  13.         jmvogtle@gamera.cns.syr.edu (John M Vogtle),
  14.         cks@hawkwind.utcs.toronto.edu (Chris Siebenmann),
  15.         ccw@deakin.OZ.AU (Craig Warren), rr@mips.COM (Robert "Bob" Rodriguez),
  16.         munck@Stars.Reston.Unisys.COM (Bob Munck)
  17. Cc: jamesp@metolius.WR.TEK.COM (James Perkins)
  18. Subject: Vmail - version 10/87DAS - part 3/3
  19. Reply-To: jamesp@metolius.WR.TEK.COM (James T. Perkins)
  20. X-Mailer: Rand MH 6.6 - Vmail 10/87DAS - Vmailtool V1.14 91/02/27
  21. Date: Mon, 11 Mar 91 11:46:40 PST
  22. From: James T Perkins <jamesp@metolius.WR>
  23. --------
  24.  
  25.  
  26. #! /bin/sh
  27. # This is a shell archive.  Remove anything before this line, then unpack
  28. # it by saving it into a file and typing "sh file".  To overwrite existing
  29. # files, type "sh file -c".  You can also feed this as standard input via
  30. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  31. # will see the following message at the end:
  32. #        "End of archive 3 (of 3)."
  33. # Contents:  load.c
  34. # Wrapped by jamesp@metolius on Mon Mar 11 11:20:05 1991
  35. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  36. if test -f load.c -a "${1}" != "-c" ; then 
  37.   echo shar: Will not over-write existing file \"load.c\"
  38. else
  39. echo shar: Extracting \"load.c\" \(11899 characters\)
  40. sed "s/^X//" >load.c <<'END_OF_load.c'
  41. X#ifndef lint
  42. Xstatic char *RCS_load_c = "$Id: load.c,v 1.5 90/07/31 11:29:15 rogers Exp $";
  43. X#endif
  44. X
  45. X/* --------------------
  46. X    vmail -- load.c
  47. X
  48. X    Routines to find folders, find all mail items in folders.  Empty
  49. X    folders are ignored.
  50. X
  51. X    Copyright (C) J. Zobel, University of Melbourne, October 1987.
  52. X-------------------- */
  53. X
  54. X#include "defs.h"
  55. X#include <ctype.h>
  56. X
  57. X
  58. X/* --------------------
  59. X    Find all folders in mail directory, set up linked list.
  60. X-------------------- */
  61. Xvoid
  62. Xfind_folders()
  63. X{
  64. X    struct direct *dp;
  65. X    struct stat statbuf;
  66. X    DIR        *dirp;
  67. X    int        i, max = 0, n = 0, scmp();
  68. X    char    str[LEN], **fds, **ftmp;
  69. X    folder    tmp, last = (folder) NULL;
  70. X
  71. X    (void)stat(mail_dir, &statbuf);
  72. X        /* guess number of folders - 10 is an error bound */
  73. X    max = statbuf.st_nlink+10;
  74. X#ifdef sparc
  75. X    ftmp = fds = (char **) memalign((unsigned)8, (unsigned)(sizeof(char *) * max));
  76. X#else
  77. X    ftmp = fds = (char **) malloc((unsigned)(sizeof(char *) * max));
  78. X#endif
  79. X    dirp = opendir(mail_dir);
  80. X    for(dp=readdir(dirp) ; dp != (struct direct *)NULL ; dp=readdir(dirp)) {
  81. X        if(strcmp(dp->d_name, ".") == 0)
  82. X            continue;
  83. X        if(strcmp(dp->d_name, "..") == 0)
  84. X            continue;
  85. X        (void)sprintf(str, "%s/%s", mail_dir, dp->d_name);
  86. X        (void)stat(str, &statbuf);
  87. X        if(! (statbuf.st_mode & S_IFDIR))
  88. X            continue;
  89. X        if(! (statbuf.st_mode & S_IREAD) || ! (statbuf.st_mode & S_IWRITE)
  90. X                || ! (statbuf.st_mode & S_IEXEC)) {
  91. X            (void)printf("Folder %s unreadable.\n", dp->d_name);
  92. X            continue;
  93. X        }
  94. X        if(n == max){
  95. X            int offset = ftmp - fds;    /* how far into fds    */
  96. X
  97. X            /*
  98. X             * We just overflowed the guessed number of entries
  99. X             * Let's try 10 more.
  100. X             */
  101. X            max += 10;
  102. X            fds = (char **)realloc((char *)fds, (unsigned)(sizeof(char *) * max));
  103. X            ftmp = fds + offset;
  104. X        }
  105. X
  106. X        *ftmp = NEWSTR(strlen(dp->d_name)+1);
  107. X        (void)strcpy(*ftmp, dp->d_name);
  108. X        n++, ftmp++;
  109. X    }
  110. X    (void)closedir(dirp);
  111. X    if(n == 0) {
  112. X        (void)printf("No folders.\n");
  113. X        exit(1);
  114. X    }
  115. X    qsort((char *)fds, n, sizeof(char *), scmp);
  116. X    for(i=0, ftmp=fds ; i < n ; ftmp++, i++) {
  117. X        tmp = NEW(mail_folder);
  118. X        tmp->name = *ftmp;
  119. X        tmp->last = tmp->mail = (item) NULL;
  120. X        tmp->pages = tmp->pagenum = 1;
  121. X        tmp->valid = false;
  122. X        tmp->prev = last;
  123. X        tmp->next = (folder) NULL;
  124. X        if(last != (folder) NULL)
  125. X            last->next = tmp;
  126. X        else
  127. X            folders = tmp;
  128. X        last = tmp;
  129. X    }
  130. X}
  131. X
  132. X
  133. Xint
  134. Xscmp(p, q)
  135. X    char    **p, **q;
  136. X{
  137. X    return(strcmp(*p, *q));
  138. X}
  139. X
  140. X
  141. X/* --------------------
  142. X    Find all mail items in given folder, throw away folder record if no
  143. X    mail items.  Returns next folder in linked list, adds new folder
  144. X    records to linked list if original record overflows.
  145. X-------------------- */
  146. Xfolder
  147. Xfind_mail(flr, load_time)
  148. X    folder    flr;
  149. X    int        load_time;
  150. X{
  151. X    struct direct *dp, *readdir();
  152. X    DIR        *dirp, *opendir();
  153. X    int        i, n = 0, items[MAXITEMS], *itmp = items, dcmp();
  154. X    char    str[LEN];
  155. X    item    tmp, last = (item) NULL;
  156. X    folder    new_folder();
  157. X
  158. X    (void)sprintf(str, "%s/%s", mail_dir, flr->name);
  159. X    dirp = opendir(str);
  160. X    if(dirp == (DIR *) NULL) {
  161. X        if(load_time)
  162. X            (void)printf("%s: strange folder.\n", str);
  163. X    } else {
  164. X        for(dp=readdir(dirp) ; dp!=(struct direct *) NULL ; dp=readdir(dirp)) {
  165. X                    /* get numbers of all mail items */
  166. X            if(n >= MAXITEMS) {
  167. X                no_control();
  168. X                (void)printf("\nMore than %d items in folder.\n",MAXITEMS-1);
  169. X                exit(1);
  170. X            }
  171. X                /* ignore anything that is not string of digits */
  172. X            if(! digits(dp->d_name))
  173. X                continue;
  174. X                    /* assume any file that is string of digits is a mail
  175. X                       item and not a directory */
  176. X            *itmp = atoi(dp->d_name);
  177. X            n++, itmp++;
  178. X        }
  179. X        (void)closedir(dirp);
  180. X    }
  181. X    if(n == 0) {        /* Empty folder - delete from list */
  182. X        flr->valid = EMPTY;
  183. X        if(load_time)
  184. X            (void)printf("\t%s: empty\n", flr->name);
  185. X        if(flr->prev != (folder) NULL)
  186. X            flr->prev->next = flr->next;
  187. X        else
  188. X            folders = flr->next;
  189. X        if(flr->next != (folder) NULL)
  190. X            flr->next->prev = flr->prev;
  191. X        return(flr->next);
  192. X    } else
  193. X        qsort((char *)items, n, sizeof(int), dcmp);
  194. X    if(load_time)        /* show status of folder */
  195. X        if(n == 1)
  196. X            (void)printf("\t%s: %d\n", flr->name, *items);
  197. X        else
  198. X            (void)printf("\t%s: %d-%d (%d items)\n",flr->name,*items,*(items+n-1),n);
  199. X    for(i=0, itmp=items ; i < n ; itmp++, i++) {
  200. X            /* add item to list of items in folder */
  201. X        tmp = NEW(mail_item);
  202. X        get_title(flr, tmp, *itmp);
  203. X        if(i % lines == 0 && last != (item) NULL) {
  204. X                /* add new record for folder */
  205. X            flr->last = last;
  206. X            flr = new_folder(flr);
  207. X            last = (item) NULL;
  208. X        }
  209. X        tmp->next = (item) NULL;
  210. X        tmp->prev = last;
  211. X        if(last != (item) NULL)
  212. X            last->next = tmp;
  213. X        else
  214. X            flr->mail = tmp;
  215. X        last = tmp;
  216. X    }
  217. X    flr->last = last;
  218. X    return(flr->next);
  219. X}
  220. X
  221. X
  222. Xint
  223. Xdcmp(a, b)
  224. X    int        *a, *b;
  225. X{
  226. X    return(*a - *b);
  227. X}
  228. X
  229. X
  230. X/* --------------------
  231. X    Return true if string consists only of digits.
  232. X-------------------- */
  233. Xint
  234. Xdigits(str)
  235. X    char    *str;
  236. X{
  237. X    for( ; *str != '\0' ; str++)
  238. X        if(! isdigit(*str))
  239. X            return(false);
  240. X    return(true);
  241. X}
  242. X
  243. X
  244. X/* --------------------
  245. X    Make header line from mail item.
  246. X-------------------- */
  247. Xvoid
  248. Xget_title(flr, mail, num)
  249. X    folder    flr;
  250. X    item    mail;
  251. X    int        num;
  252. X{
  253. X    FILE    *fp, *fopen();
  254. X    char    date[10], str[LEN], subj[42], from[20], to[16], fill[42];
  255. X    char    repl = ' ', *first(), *s, *fgets();
  256. X    int        i;
  257. X
  258. X    subj[0] = from[0] = to[0] = fill[0] = '\0';
  259. X    (void)sprintf(str, "%s/%s/%d", mail_dir, flr->name, num);
  260. X    fp = fopen(str, "r");
  261. X    while((s=fgets(str, LEN, fp)) != (char *) NULL && *str != '\n') {
  262. X            /* while not eof and reading header */
  263. X        str[strlen(str)-1] = '\0';
  264. X            /* should also check date */
  265. X        if(! lstrncmp("date:", str, 5))
  266. X            get_date(str+5, date);
  267. X        else if(! lstrncmp("subject:", str, 8)) {
  268. X            s = first(str+8);
  269. X            (void)strncpy(subj, s, 41);
  270. X            subj[41] = '\0';
  271. X        } else if(! lstrncmp("replied:", str, 8))
  272. X            repl = '-';
  273. X        else if(! lstrncmp("from:", str, 5)) {
  274. X            s = first(str+5);
  275. X            if(! isuser(s)) {
  276. X                (void)strncpy(from, s, 19);
  277. X                from[19] = '\0';
  278. X            }
  279. X        } else if(! lstrncmp("to:", str, 3)) {
  280. X            s = first(str+3);
  281. X            (void)strncpy(to, s, 15);
  282. X            to[15] = '\0';
  283. X        } else if(! lstrncmp("apparently-to:", str, 14)) {
  284. X            s = first(str+14);
  285. X            (void)strncpy(to, s, 15);
  286. X            to[15] = '\0';
  287. X        }
  288. X    }
  289. X    if(s != (char *) NULL) {
  290. X        for(i=0 ; i < 42 && fgets(str, LEN, fp) != (char *) NULL ;) {
  291. X            str[strlen(str)-1] = ' ';
  292. X            (void)strncpy(fill+i, str, 42-i);
  293. X            i += strlen(str);
  294. X        }
  295. X        fill[41] = '\0';
  296. X    }
  297. X    (void)fclose(fp);
  298. X    if(subj[0] == '\0')
  299. X        (void)strcpy(subj, "(none)");
  300. X    flatten(subj);
  301. X    flatten(fill);
  302. X    if(from[0] == '\0')
  303. X        (void)sprintf(str, "  %8s %cTo: %-15s  %s << %s",date,repl,to,subj,fill);
  304. X    else
  305. X        (void)sprintf(str, "  %8s %c%-19s  %s << %s",date,repl,from,subj,fill);
  306. X    str[cols-6] = '\0';
  307. X    mail->title = NEWSTR(strlen(str)+1);
  308. X    mail->number = num;
  309. X    (void)strcpy(mail->title, str);
  310. X}
  311. X
  312. X
  313. X#ifdef USDATE
  314. X#define DAY1    date[3]
  315. X#define DAY2    date[4]
  316. X#define MTH1    date[0]
  317. X#define MTH2    date[1]
  318. X#else
  319. X#define DAY1    date[0]
  320. X#define DAY2    date[1]
  321. X#define MTH1    date[3]
  322. X#define MTH2    date[4]
  323. X#endif
  324. X#define YR1        date[6]
  325. X#define YR2        date[7]
  326. X
  327. X/* --------------------
  328. X    Get date from first argument; assumes format is one of
  329. XDate: Fri, 3 Apr 87 ...                        (a)
  330. XDate: Wed, 17 Jun 87 ...                    (b)
  331. XDate: 07 Sep 87 ...                            (c)
  332. XDate: Tue Sep 29 12:27:01 EST 1987            (d)
  333. X    Dates are put into Imperial form (dd-mm-yy), or US form (mm-dd-yy)
  334. X    if -DUSDATE is set.
  335. X
  336. X    This routine should be more flexible re: recognizing date formats.
  337. X-------------------- */
  338. Xvoid
  339. Xget_date(str, date)
  340. X    char    *str, *date;
  341. X{
  342. X    int        i;
  343. X    bool    get_month();
  344. X    char    *next_token();
  345. X
  346. X    date[2] = date[5] = '-';
  347. X    date[8] = '\0';
  348. X    for(; *str == ' ' || *str == '\t' ; str++)
  349. X        ;
  350. X    if(*str == '\0')
  351. X        goto unknown;
  352. X    if(! isdigit(*str))        /* day of month not first field */
  353. X        str = next_token(str);        /* skip day of week */
  354. X    if(str == (char *) NULL + 1)
  355. X        goto unknown;
  356. X
  357. X    if(isdigit(*str)) {        /* one of (a), (b) or (c) formats */
  358. X        if(isdigit(*(str+1)))    /* two-number date */
  359. X#ifdef USDATE
  360. X            DAY1 = *str, DAY2 = *(++str);
  361. X        else
  362. X            DAY1 = '0', DAY2 = *str;
  363. X#else
  364. X            DAY1 = (*str == '0') ? ' ' : *str, DAY2 = *(++str);
  365. X        else
  366. X            DAY1 = ' ', DAY2 = *str;
  367. X#endif
  368. X        str = next_token(str);    /* go to month */
  369. X        if(str == (char *) NULL + 1)
  370. X            goto unknown;
  371. X        if(! get_month(str, date))
  372. X            goto unknown;
  373. X        str = next_token(str);    /* go to year */
  374. X        if(str == (char *) NULL + 1)
  375. X            goto unknown;
  376. X        if(! isdigit(*str) || ! isdigit(*(str+1)))
  377. X            goto unknown;
  378. X        YR1 = *str, YR2 = *(str+1);
  379. X    } else {    /* format (d) */
  380. X        if(! get_month(str, date))
  381. X            goto unknown;
  382. X        str = next_token(str);    /* go to day */
  383. X        if(str == (char *) NULL + 1)
  384. X            goto unknown;
  385. X        if(! isdigit(*str) || ! isdigit(*(str+1)))
  386. X            goto unknown;
  387. X#ifdef USDATE
  388. X        DAY1 = *str, DAY2 = *(++str);
  389. X#else
  390. X        DAY1 = (*str == '0') ? ' ' : *str, DAY2 = *(++str);
  391. X#endif
  392. X        str += strlen(str) - 2;        /* go to year */
  393. X        if(! isdigit(*str) || ! isdigit(*(str+1)))
  394. X            goto unknown;
  395. X        YR1 = *str, YR2 = *(str+1);
  396. X    }
  397. X    return;        /* date is ok */
  398. X
  399. Xunknown:            /* erase date */
  400. X    for(i=0 ; i < 8 ; i++)
  401. X        date[i] = ' ';
  402. X}
  403. X
  404. X
  405. Xstatic char *month[] = {
  406. X    "jan", "feb", "mar", "apr", "may", "jun",
  407. X    "jul", "aug", "sep", "oct", "nov", "dec"
  408. X};
  409. X
  410. X/* --------------------
  411. X    Put the month from the first part of str in date as a number.
  412. X-------------------- */
  413. Xbool
  414. Xget_month(str, date)
  415. X    char    *str, *date;
  416. X{
  417. X    int        i;
  418. X
  419. X    for(i=0 ; i < 12 && lstrncmp(month[i], str, 3) != 0 ; i++)
  420. X        ;
  421. X    if(i == 12)        /* string doesn't match month */
  422. X        return(false);
  423. X    else {    
  424. X        if(i < 9)    /* single digit month */
  425. X#ifdef USDATE
  426. X            MTH1 = ' ', MTH2 = i + '0' + 1;
  427. X#else
  428. X            MTH1 = '0', MTH2 = i + '0' + 1;
  429. X#endif
  430. X        else
  431. X            MTH1 = '1', MTH2 = i + '0' - 9;
  432. X        return(true);
  433. X    }
  434. X}
  435. X
  436. X
  437. X/* --------------------
  438. X    Replace tabs and newlines in string by spaces.
  439. X    Compress multiple spaces to a single space.
  440. X-------------------- */
  441. Xvoid
  442. Xflatten(str)
  443. X    char    *str;
  444. X{
  445. X    char    prev = ' ', *s = str;
  446. X
  447. X    /* advance str monotonically, copying into s as necessary */
  448. X
  449. X    while (*str)
  450. X    {
  451. X        /* change funny character to space */
  452. X        if (!isgraph(*str)) {
  453. X        *str = ' ';
  454. X        }
  455. X
  456. X        /* copy character into new position */
  457. X        *s = *str;
  458. X
  459. X        /* advance new string pointer, but compress multiple spaces */
  460. X        if (isgraph(*str) || prev != ' ') {
  461. X        prev = *s;
  462. X        s++;
  463. X        }
  464. X        str++;
  465. X    }
  466. X    *s = '\0';
  467. X}
  468. X
  469. X
  470. X/* --------------------
  471. X    Return pointer to first non-white character in string.
  472. X-------------------- */
  473. Xchar *
  474. Xfirst(str)
  475. X    char    *str;
  476. X{
  477. X    for(; *str == ' ' || *str == '\t' || *str == '\n' ; str++)
  478. X        ;
  479. X    return(str);
  480. X}
  481. X
  482. X
  483. X/* --------------------
  484. X    Check given string for occurence of user's name.
  485. X-------------------- */
  486. Xint
  487. Xisuser(str)
  488. X    char    *str;
  489. X{
  490. X    int        len = strlen(user);
  491. X
  492. X    for(; *str != '\0' ; str++)
  493. X            /* assume all chars in all unames alphanumeric */
  494. X        if(*str == *user && strncmp(str, user, len) == 0 &&
  495. X                (*(str+len) < 'a' || *(str+len) > 'z') &&
  496. X                (*(str+len) < 'A' || *(str+len) > 'Z') &&
  497. X                (*(str+len) < '0' || *(str+len) > '9'))
  498. X            return(true);
  499. X    return(false);
  500. X}
  501. X
  502. X
  503. X/* --------------------
  504. X    Make a new folder record.
  505. X-------------------- */
  506. Xfolder
  507. Xnew_folder(flr)
  508. X    folder    flr;
  509. X{
  510. X    folder    f;
  511. X
  512. X    f = NEW(mail_folder);
  513. X    f->prev = flr;
  514. X    f->next = flr->next;
  515. X    flr->next = f;
  516. X    if(f->next != (folder) NULL)
  517. X        f->next->prev = f;
  518. X    f->pagenum = f->pages = flr->pages + 1;
  519. X    f->name = flr->name;
  520. X    f->valid = true;
  521. X    f->mail = f->last = (item) NULL;
  522. X    flr = f;
  523. X    for(f=f->prev; f != (folder) NULL && f->name == flr->name ; f=f->prev)
  524. X        f->pages = flr->pages;
  525. X    return(flr);
  526. X}
  527. X
  528. X
  529. X/* --------------------
  530. X    Find next free slot in directory for mail item (that is, find next
  531. X    unused number) -- structures in vmail may not be up to date if user
  532. X    has initiated a "send" process.
  533. X-------------------- */
  534. Xint
  535. Xnext_vacant(flr)
  536. X    folder    flr;
  537. X{
  538. X    struct direct *dp, *readdir();
  539. X    DIR        *dirp, *opendir();
  540. X    char    str[LEN];
  541. X    int        i, n = 0;
  542. X
  543. X    (void)sprintf(str, "%s/%s", mail_dir, flr->name);
  544. X    dirp = opendir(str);
  545. X    for(dp=readdir(dirp) ; dp != (struct direct *) NULL ; dp=readdir(dirp)) {
  546. X            /* ignore anything that is not string of digits */
  547. X        if(! digits(dp->d_name))
  548. X            continue;
  549. X        if((i = atoi(dp->d_name)) > n)
  550. X            n = i;
  551. X    }
  552. X    (void)closedir(dirp);
  553. X    return(n+1);
  554. X}
  555. END_OF_load.c
  556. if test 11899 -ne `wc -c <load.c`; then
  557.     echo shar: \"load.c\" unpacked with wrong size!
  558. fi
  559. # end of overwriting check
  560. fi
  561. echo shar: End of archive 3 \(of 3\).
  562. cp /dev/null ark3isdone
  563. MISSING=""
  564. for I in 1 2 3 ; do
  565.     if test ! -f ark${I}isdone ; then
  566.     MISSING="${MISSING} ${I}"
  567.     fi
  568. done
  569. if test "${MISSING}" = "" ; then
  570.     echo You have unpacked all 3 archives.
  571.     rm -f ark[1-9]isdone
  572. else
  573.     echo You still need to unpack the following archives:
  574.     echo "        " ${MISSING}
  575. fi
  576. ##  End of shell archive.
  577. exit 0
  578.